package com.wangtao.rpc.netty;

import com.sun.jmx.snmp.ServiceName;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.lang.reflect.Proxy;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class NettyClient {

    //线程池
    private static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2);

    //自定义Handler
    private static NettyClientHandler client;

    public static void initClient() {
        client = new NettyClientHandler();
        EventLoopGroup group = new NioEventLoopGroup();

        try {

            //创建客户端的启动对象
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group) ////设置一个线程组
                    .channel(NioSocketChannel.class) //用NioSocketChannel作为客户端的通道实现
                    .option(ChannelOption.TCP_NODELAY, true) //禁止数据合并后在发送，适用于小数据发送
                    .handler(new ChannelInitializer<SocketChannel>() {  //给group的EventLoop设置对应的管道处理器
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            pipeline.addLast(new StringEncoder()); //添加编码器
                            pipeline.addLast(new StringDecoder()); //添加解码器
                            pipeline.addLast(client);  //添加自定义Handler,业务全在这里面
                        }
                    });

            //连接服务器端
            bootstrap.connect("127.0.0.1", 9999).sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //创建代理对象
    public static Object getBean(final Class<?> clazz, final String ServiceName) {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{clazz},
                (proxy, method, args) -> {
                    if (client == null) {
                        //初始化Handler
                        initClient();
                    }

                    //设置参数
                    client.setParams(ServiceName + args[0]);
                    //线程执行，get方法阻塞直到有结果返回
                    return executorService.submit(client).get();
                });
    }
}
